#include "Wire.h"
#include "Clock.h"

Clock::Clock(uint8_t address)
{
	m_address = address;
}

void Clock::begin()
{
	Wire.begin();
	beat();
}

void Clock::beat()
{
	get(m_year, m_month, m_hour, m_minute, m_second, m_dayOfWeek, m_dayOfMonth);
}

void Clock::set(uint8_t year, uint8_t month, uint8_t dayOfMonth, uint8_t hour, uint8_t minute, uint8_t second, uint8_t dayOfWeek)
{
   Wire.beginTransmission(m_address);
   Wire.write((uint8_t)0x00);
   Wire.write(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}

void Clock::get(uint8_t& year, uint8_t& month, uint8_t& hour, uint8_t& minute, uint8_t& second, uint8_t& dayOfWeek, uint8_t& dayOfMonth)
{
  Wire.beginTransmission(m_address);
  Wire.write((uint8_t)0x00);
  Wire.endTransmission();

  Wire.requestFrom(m_address, (uint8_t)7);

  // A few of these need masks because certain bits are control bits
  second     = bcdToDec(Wire.read() & 0x7f);
  minute     = bcdToDec(Wire.read());
  hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  dayOfWeek  = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  month      = bcdToDec(Wire.read());
  year       = bcdToDec(Wire.read());
}

uint8_t Clock::year() const
{
	return m_year;
}

uint8_t Clock::month() const
{
	return m_month;
}

uint8_t Clock::hour() const
{
	return m_hour;
}

uint8_t Clock::minute() const
{
	return m_minute;
}

uint8_t Clock::second() const
{
	return m_second;
}

uint8_t Clock::dayOfWeek() const
{
	return m_dayOfWeek;
}

uint8_t Clock::dayOfMonth() const
{
	return m_dayOfMonth;
}

unsigned int Clock::now() const
{
	return (m_hour*1800U + m_minute*30U + m_second/2U);
}

uint8_t Clock::bcdToDec(uint8_t val) const
{
  return ( (val/16*10) + (val%16) );
}

uint8_t Clock::decToBcd(uint8_t val) const
{
  return ( (val/10*16) + (val%10) );
}
